package com.sgcc.epri.dcloud.controller;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sgcc.epri.dcloud.mapper.dm.TreeMapper;
import com.sgcc.epri.dcloud.pojo.Result;
import com.sgcc.epri.dcloud.pojo.TreeNode;
import com.sgcc.epri.dcloud.service.ComputeService;
import com.sgcc.epri.dcloud.util.ChoreUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.concurrent.CompletableFuture;


@RestController
@RequestMapping("/compute")
@Api(description = "指标计算")
public class ComputeController {

    private final Logger log =  LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ComputeService computeService;

    @GetMapping("/byTreeIdStartTask")
    @ApiOperation(value = "通过某一级的树形结构id来启动计算任务（该级必须是文件属性）; 电量和非电量要分开跑的话要用两套id")
    public Result startTask(@RequestParam(required = true) @ApiParam(value = "树形结构id", name = "treeId", required = true) String treeId,
                            @RequestParam(required = true) @ApiParam(value = "数据类型：all（全部）、电量（0）、非电量（1）", name = "dataType", required = true) String dataType,
                            @RequestParam(required = true) @ApiParam(value = "对象id：all（全部）、若选择请用逗号将id隔开传递", name = "objectIds", required = true) String objectIds) {
        TreeNode treeNode = treeMapper.selectOne(new QueryWrapper<TreeNode>().eq("id", treeId));
        if (ChoreUtil.dateIsBefore(treeNode.getCalStopTime(), DateUtil.now().substring(0, 10))) {
            return Result.success("已过计算截止时间，此报表将不再计算。");
        }
        computeService.startTask(treeId, dataType, objectIds);
        return Result.success("任务已开始，请稍后查询任务状态。");

    }

    // 需展示近几个小时的
    @GetMapping("/byTreeIdCheckTask")
    @ApiOperation(value = "【该接口需采用循环调用；该接口只返回近24小时的数据，须在页面中注明】通过某一级的树形结构id来查询计算任务状态（该级必须是文件属性）；状态解释：executionIng（执行中）、executionCompleted（执行完成）、executionFailed（执行失败）；返回列对应中文名 data_type:数据类型、objectid:对象id、status:状态、create_at:任务启动时间/上次更新时间")
    public Result checkTaskCompletion(@RequestParam(required = true) @ApiParam(value = "树形结构ID", name = "treeId", required = true) String treeId) {
        return computeService.checkTaskCompletion(treeId);
    }

    @GetMapping("/manualOperation")
    @ApiOperation(value = "【当前计算周期请在配置文件中查看auto-task-exetime配置项】手动计算所有设置为自动计算的任务")
    public void manualOperation(){
        autoCompute();
    }


    @Autowired
    private TreeMapper treeMapper;

    @Async("threadPoolTaskExecutor")
    @Scheduled(cron = "${auto-task-exetime}")
    public void autoCompute() {
        try{
            log.info("开始执行自动计算任务...");
            // 优先确定那些节点需要计算？
            QueryWrapper<TreeNode> tqw = new QueryWrapper<>();
            tqw.eq("file_type", "1"); // 1表示该节点是文件属性
            tqw.eq("auto_flag", "0"); // 0表示自动计算
            List<TreeNode> treeNodes = treeMapper.selectList(tqw);
            if (treeNodes.size() == 0) {
                log.info("检查后发现并无需要计算的任务，任务终止！");
                return;
            }
            treeNodes.forEach(treeNode -> computeService.startTask(treeNode.getId()+"", "all", "all"));
            log.info("执行自动计算任务完成!");
        }catch (Exception e){
            e.printStackTrace();
            log.error("自动计算任务失败，具体错误如下");
            log.error(""+e);
        }
    }

}
